﻿/*****************************************************************
 * Copyright (C) Newegg Corporation. All rights reserved.
 * 
 * Author       :  Bill Li (Bill.S.Li@newegg.com)
 * Create Date  :  
 * Usage        :  
 *
 * RevisionHistory
 * Date         Author               Description
 * 
*****************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Framework;
using System.Collections.Specialized;

namespace TemplateEngine
{
    /// <summary>
    /// 模板文档类
    /// </summary>
    public class TemplateDocument
    {
        private string _templatestr;

        private string _body;

        private NameValueCollection _param;

        internal NameValueCollection Param
        {
            get { return _param; }
        }

        /// <summary>
        /// 验证字符串是否符合规范
        /// </summary>

        private List<TranslateHalfNode> _translateNode;

        private List<TemplateNode> _rootLst;

        internal List<TemplateNode> RootLst
        {
            get { return _rootLst; }
            set { _rootLst = value; }
        }

        internal string Body
        {
            get
            {
                return _body;
            }
        }

        #region 构造函数
        private TemplateDocument()
        {
            TemplateLogger.Info("实例化模板适配器");
            _translateNode = new List<TranslateHalfNode>();
            _param = new NameValueCollection();
        }

        /// <summary>
        /// TemplateDocument构造函数
        /// </summary>
        /// <param name="templateStr">模板字符串</param>
        public TemplateDocument(string templateStr)
            : this()
        {
            this._templatestr = templateStr;

            Resolve();
        }

        /// <summary>
        /// TemplateDocument构造函数
        /// </summary>
        /// <param name="templatePath">模板路径</param>
        /// <param name="encode">字符编码方式</param>
        public TemplateDocument(string templatePath, Encoding encode)
            : this()
        {
            using (StreamReader sr = new StreamReader(templatePath, encode))
            {
                this._templatestr = sr.ReadToEnd();
            }

            Resolve();
        }

        /// <summary>
        /// TemplateDocument构造函数
        /// </summary>
        /// <param name="templateStream">模板流</param>
        /// <param name="encode">字符编码方式</param>
        public TemplateDocument(Stream templateStream, Encoding encode)
            : this()
        {
            using (StreamReader sr = new StreamReader(templateStream, encode))
            {
                this._templatestr = sr.ReadToEnd();
            }

            Resolve();
        }
        #endregion

        /// <summary>
        /// 模板解释方法
        /// </summary>
        /// <param name="dataXml">xml数据源</param>
        /// <returns></returns>
        public string Translate(string dataXml, NameValueCollection nv)
        {
            _param = nv;
            return Translate(dataXml);
        }

        /// <summary>
        /// 模板解释方法
        /// </summary>
        /// <param name="dataXml">xml数据源</param>
        /// <returns></returns>
        public string Translate(string dataXml)
        {
            TemplateLogger.Debugger("开始模板翻译：数据源为：" + dataXml);
            TemplateLogger.LoadLogging("开始调用.net XmlDocument");
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(dataXml);
            TemplateLogger.LoadLogging("载入XML字符串结束");

            TemplateLogger.LoadLogging("开始翻译节点");
            string str = this._rootLst[0].TranslateNode(doc);
            TemplateLogger.LoadLogging("结束翻译节点");

            TemplateLogger.Debugger("模板翻译结果：" + str);

            return str;
        }

        /// <summary>
        /// 新文档解析函数，摒弃正则表达式
        /// </summary>
        private void Resolve()
        {
            const string bodyNode = "<tag:body";
            TemplateLogger.LoadLogging("开始Resolve函数");
            TemplateLogger.Debugger("开始模板解析：模板数据为" + this._templatestr);

            // 为模板加根节点
            if (this._templatestr.IndexOf(bodyNode) == -1)
            {
                this._body = "<tag:body>" + _templatestr + "</tag:body>";
            }
            else
            {
                _body = _templatestr;
            }

            this._body = this._body.Replace("<%", "<tag:show>");
            this._body = this._body.Replace("%>", "</tag:show>");

            _rootLst = new List<TemplateNode>();
            _translateNode = NodeTranslateUtil.FindAllHalfNode(_body);

            TemplateNode currentNode = null;

            // 组装文档对象
            foreach (var halfNode in _translateNode)
            {
                // 进行根节点处理
                if (currentNode == null)
                {
                    currentNode = new TemplateNode();
                    // 进行组装
                    if (!halfNode.IsStartNode)
                    {
                        throw new TemplateEngineException("解析异常：节点" + halfNode._nodeStr + "应该是开始节点");
                    }

                    // 组装node对象
                    currentNode.Document = this;
                    currentNode.startNode = halfNode._nodeStr;
                    currentNode.startNodeIdx = halfNode._nodeIdx;
                    currentNode.CommandStr = halfNode.TranslateCommand;
                    currentNode.Root = currentNode;
                    _rootLst.Add(currentNode);
                }
                else
                {
                    // 如果是开始截点，加入匹配队列
                    if (halfNode.IsStartNode)
                    {
                        TemplateNode tempNode = new TemplateNode();

                        // 建立父子关系
                        tempNode.Document = this;
                        tempNode.Parent = currentNode;
                        currentNode = tempNode;
                        tempNode = null;
                        currentNode.Parent.Nodes.Add(currentNode);

                        // 为当前截点赋值
                        currentNode.CommandStr = halfNode.TranslateCommand;
                        currentNode.startNodeIdx = halfNode._nodeIdx;
                        currentNode.startNode = halfNode._nodeStr;

                        if (halfNode.IsCompletedNode)
                        {
                            currentNode.endNode = halfNode._nodeStr;
                            currentNode.endNodeIdx = halfNode._nodeIdx;
                            currentNode.IsResolved = true;
                            currentNode = currentNode.Parent;
                        }
                    }
                    else
                    {
                        // 如果当前节点没有匹配完成，直接匹配当前节点
                        if (currentNode.IsResolved)
                        {
                            // 匹配父节点
                            currentNode = currentNode.Parent;
                        }

                        if (currentNode.CommandStr != halfNode.TranslateCommand)
                        {
                            throw new TemplateEngineException("模板解析错误！结束节点标记应该是</tag:" + currentNode.CommandStr + ";但是实际结束截点是" + halfNode.TranslateCommand);
                        }

                        currentNode.endNodeIdx = halfNode._nodeIdx;
                        currentNode.endNode = halfNode._nodeStr;
                        currentNode.IsResolved = true;

                        // 节点配对完成后指向父节点
                        currentNode = currentNode.Parent;
                    }
                }
            }

            if (this._rootLst.Count == 0)
            {
                // 无节点，直接退出
                return;
            }

            // 递归对所有节点进行值绑定
            foreach (var root in this._rootLst)
            {
                root.Initialize();

                foreach (var item in root.Nodes)
                {
                    BindNodeValue(item);
                }
            }

            TemplateLogger.LoadLogging("结束Resolve函数");
            TemplateLogger.Debugger("模板解析结束");
        }

        /// <summary>
        /// 绑定节点值
        /// </summary>
        private void BindNodeValue(TemplateNode node)
        {
            node.Initialize();

            foreach (var item in node.Nodes)
            {
                BindNodeValue(item);
            }
        }
    }
}
